<template>
  <div class="main">
    <el-card class="box-card">
      <template #header>
        <div class="card-header">
          <span>菜单管理</span>
          <div class="header-actions">
            <el-button type="primary" @click="handleAdd()">
              <IconifyIconOffline icon="ep:plus" />
              新增菜单
            </el-button>
            <el-button @click="handleRefresh">
              <IconifyIconOffline icon="ep:refresh" />
              刷新
            </el-button>
          </div>
        </div>
      </template>

      <div class="content">
        <!-- 搜索区域 -->
        <div class="search-container">
          <el-form :model="searchForm" inline>
            <el-form-item label="菜单名称">
              <el-input
                v-model="searchForm.name"
                placeholder="请输入菜单名称"
                clearable
                style="width: 200px"
              />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="handleSearch">
                <IconifyIconOffline icon="ep:search" />
                搜索
              </el-button>
              <el-button @click="handleReset">
                <IconifyIconOffline icon="ep:refresh-left" />
                重置
              </el-button>
            </el-form-item>
          </el-form>
        </div>

        <!-- 菜单树表格 -->
        <el-table
          v-loading="loading"
          :data="menuList"
          row-key="id"
          :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
          border
          stripe
          style="width: 100%"
        >
          <el-table-column prop="name" label="菜单名称" min-width="200">
            <template #default="{ row }">
              <div class="menu-name">
                <IconifyIconOffline
                  v-if="row.icon"
                  :icon="row.icon"
                  style="margin-right: 8px; color: #409eff"
                />
                <span>{{ row.name }}</span>
              </div>
            </template>
          </el-table-column>

          <el-table-column prop="path" label="路由路径" min-width="150" />

          <el-table-column prop="component" label="组件路径" min-width="150" />

          <el-table-column prop="type" label="类型" width="80">
            <template #default="{ row }">
              <el-tag :type="getTypeTagType(row.type)">
                {{ getTypeText(row.type) }}
              </el-tag>
            </template>
          </el-table-column>

          <el-table-column prop="perms" label="权限标识" min-width="120" />

          <el-table-column prop="sort" label="排序" width="80" />

          <el-table-column label="操作" width="200" fixed="right">
            <template #default="{ row }">
              <el-button type="primary" size="small" @click="handleAdd(row.id)">
                新增
              </el-button>
              <el-button type="success" size="small" @click="handleEdit(row)">
                编辑
              </el-button>
              <el-button type="danger" size="small" @click="handleDelete(row)">
                删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </el-card>

    <!-- 菜单表单对话框 -->
    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      width="600px"
      :close-on-click-modal="false"
    >
      <el-form
        ref="formRef"
        :model="formData"
        :rules="formRules"
        label-width="100px"
      >
        <el-form-item label="上级菜单" prop="parentId">
          <el-tree-select
            v-model="formData.parentId"
            :data="menuTreeOptions"
            :props="{ label: 'name', value: 'id' }"
            placeholder="请选择上级菜单"
            check-strictly
            clearable
            style="width: 100%"
          />
        </el-form-item>

        <el-form-item label="菜单类型" prop="type">
          <el-radio-group v-model="formData.type">
            <el-radio :label="0">目录</el-radio>
            <el-radio :label="1">菜单</el-radio>
            <el-radio :label="2">按钮</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="菜单名称" prop="name">
          <el-input v-model="formData.name" placeholder="请输入菜单名称" />
        </el-form-item>

        <el-form-item v-if="formData.type !== 2" label="路由路径" prop="path">
          <el-input v-model="formData.path" placeholder="请输入路由路径" />
        </el-form-item>

        <el-form-item
          v-if="formData.type === 1"
          label="组件路径"
          prop="component"
        >
          <el-input v-model="formData.component" placeholder="请输入组件路径" />
        </el-form-item>

        <el-form-item v-if="formData.type !== 2" label="菜单图标" prop="icon">
          <div class="icon-input-container">
            <el-input v-model="formData.icon" placeholder="请输入图标名称">
              <template #prepend>
                <IconifyIconOnline
                  v-if="formData.icon"
                  :icon="formData.icon"
                  style="color: #409eff"
                />
              </template>
            </el-input>
            <div class="icon-actions">
              <el-button size="small" @click="openIconPicker">选择</el-button>
              <el-button v-if="formData.icon" size="small" @click="clearIcon"
                >清空</el-button
              >
            </div>
          </div>
        </el-form-item>

        <el-form-item label="外链/内嵌" prop="isFrame">
          <el-switch v-model="formData.isFrame" />
        </el-form-item>

        <el-form-item label="权限标识" prop="perms">
          <el-input v-model="formData.perms" placeholder="请输入权限标识" />
        </el-form-item>

        <el-form-item label="排序" prop="sort">
          <el-input-number v-model="formData.sort" :min="0" :max="999" />
        </el-form-item>
      </el-form>

      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button
          :loading="submitLoading"
          type="primary"
          @click="handleSubmit"
        >
          确定
        </el-button>
      </template>
    </el-dialog>
    <!-- 图标选择器 -->
    <el-dialog
      v-model="iconPickerVisible"
      title="选择图标"
      width="620px"
      :close-on-click-modal="false"
    >
      <div class="icon-picker">
        <el-input
          v-model="iconSearch"
          placeholder="搜索图标（如 ep:user）或关键字"
          clearable
          style="margin-bottom: 12px"
        />
        <div class="icon-grid">
          <div
            v-for="icon in filteredIcons"
            :key="icon"
            class="icon-item"
            @click="selectIcon(icon)"
          >
            <IconifyIconOnline :icon="icon" style="font-size: 20px" />
            <span class="icon-name">{{ icon }}</span>
          </div>
        </div>
      </div>
      <template #footer>
        <el-button @click="iconPickerVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, computed } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import type { FormInstance, FormRules } from "element-plus";
import {
  getMenuTree,
  getMenuList,
  createMenu,
  updateMenu,
  deleteMenu,
  type MenuItem
} from "@/api/menu";
import IconifyIconOnline from "@/components/ReIcon/src/iconifyIconOnline";

defineOptions({
  name: "SystemMenu"
});

// 响应式数据
const loading = ref(false);
const menuList = ref<MenuItem[]>([]);
const menuTreeOptions = ref<MenuItem[]>([]);
const dialogVisible = ref(false);
const submitLoading = ref(false);
const isEdit = ref(false);
const currentEditId = ref<number | null>(null);

// 搜索表单
const searchForm = reactive({
  name: ""
});

// 表单数据
const formData = reactive<Partial<MenuItem>>({
  parentId: 0,
  type: 0,
  name: "",
  path: "",
  component: "",
  icon: "",
  perms: "",
  sort: 0,
  isFrame: false
});

// 表单验证规则
const formRules: FormRules = {
  name: [{ required: true, message: "请输入菜单名称", trigger: "blur" }],
  type: [{ required: true, message: "请选择菜单类型", trigger: "change" }],
  path: [
    {
      required: true,
      message: "请输入路由路径",
      trigger: "blur",
      validator: (rule, value, callback) => {
        if (formData.type !== 2 && !value) {
          callback(new Error("请输入路由路径"));
        } else {
          callback();
        }
      }
    }
  ],
  component: [
    {
      validator: (rule, value, callback) => {
        if (formData.type === 1 && !value) {
          callback(new Error("请输入组件路径"));
        } else {
          callback();
        }
      }
    }
  ]
};

const formRef = ref<FormInstance>();

// 计算属性
const dialogTitle = computed(() => (isEdit.value ? "编辑菜单" : "新增菜单"));

// 获取菜单类型标签类型
const getTypeTagType = (type: number) => {
  const typeMap = {
    0: "primary", // 目录
    1: "success", // 菜单
    2: "warning" // 按钮
  };
  return typeMap[type] || "info";
};

// 获取菜单类型文本
const getTypeText = (type: number) => {
  const typeMap = {
    0: "目录",
    1: "菜单",
    2: "按钮"
  };
  return typeMap[type] || "未知";
};

// 获取菜单列表
const fetchMenuList = async () => {
  try {
    loading.value = true;
    const response = await getMenuTree();
    if (response.code === 0) {
      menuList.value = response.data;
      // 为树形选择器准备数据
      menuTreeOptions.value = [
        {
          id: 0,
          name: "顶级菜单",
          type: 0,
          sort: 0,
          status: 1,
          visible: 1,
          children: response.data
        }
      ];
    }
  } catch (error) {
    ElMessage.error("获取菜单列表失败");
  } finally {
    loading.value = false;
  }
};

// 搜索
const handleSearch = () => {
  fetchMenuList();
};

// 重置搜索
const handleReset = () => {
  searchForm.name = "";
  fetchMenuList();
};

// 刷新
const handleRefresh = () => {
  fetchMenuList();
};

// 新增菜单（可携带父级id，作为子菜单创建）
const handleAdd = (parentId?: number) => {
  isEdit.value = false;
  currentEditId.value = null;
  resetForm();
  if (typeof parentId === "number") formData.parentId = parentId;
  dialogVisible.value = true;
};

// 编辑菜单
const handleEdit = (row: MenuItem) => {
  isEdit.value = true;
  currentEditId.value = row.id!;
  Object.assign(formData, row);
  dialogVisible.value = true;
};

// 删除菜单
const handleDelete = async (row: MenuItem) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除菜单 "${row.name}" 吗？`,
      "删除确认",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }
    );

    await deleteMenu(row.id!);
    ElMessage.success("删除成功");
    fetchMenuList();
  } catch (error) {
    if (error !== "cancel") {
      ElMessage.error("删除失败");
    }
  }
};

// 重置表单
const resetForm = () => {
  Object.assign(formData, {
    parentId: 0,
    type: 1,
    name: "",
    path: "",
    component: "",
    icon: "",
    perms: "",
    sort: 0
  });
  formRef.value?.clearValidate();
};

// 提交表单
const handleSubmit = async () => {
  if (!formRef.value) return;

  try {
    await formRef.value.validate();
    submitLoading.value = true;

    if (isEdit.value) {
      await updateMenu(currentEditId.value!, formData);
      ElMessage.success("编辑成功");
    } else {
      await createMenu(formData as Omit<MenuItem, "id">);
      ElMessage.success("新增成功");
    }

    dialogVisible.value = false;
    // 无论新增还是编辑，都重新请求菜单树并重新渲染
    fetchMenuList();
    //刷新浏览器
    window.location.reload();
  } catch (error) {
    ElMessage.error(isEdit.value ? "编辑失败" : "新增失败");
  } finally {
    submitLoading.value = false;
  }
};

// 组件挂载时获取数据
onMounted(() => {
  fetchMenuList();
});

// 图标选择器
const iconPickerVisible = ref(false);
const iconSearch = ref("");
const iconOptions = ref<string[]>([
  "ep:home-filled",
  "ep:house",
  "ep:setting",
  "ep:user",
  "ep:avatar",
  "ep:menu",
  "ep:grid",
  "ep:management",
  "ep:tools",
  "ep:document",
  "ep:folder",
  "ep:link",
  "ep:message",
  "ep:bell",
  "ep:collection",
  "ep:star",
  "ep:location",
  "ep:map-location",
  "ep:warning",
  "ep:info-filled",
  "ep:success-filled",
  "ep:circle-check",
  "ep:close",
  "ep:refresh",
  "ep:search",
  "ep:plus",
  "ep:minus",
  "ep:edit",
  "ep:delete",
  "ep:upload",
  "ep:download"
]);

const filteredIcons = computed(() => {
  const q = iconSearch.value.trim().toLowerCase();
  if (!q) return iconOptions.value;
  return iconOptions.value.filter(i => i.toLowerCase().includes(q));
});

const openIconPicker = () => {
  iconSearch.value = "";
  iconPickerVisible.value = true;
};

const selectIcon = (icon: string) => {
  formData.icon = icon;
  iconPickerVisible.value = false;
};

const clearIcon = () => {
  formData.icon = "";
};
</script>

<style scoped>
.main {
  padding: 20px;
}

.box-card {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.header-actions {
  display: flex;
  gap: 8px;
}

.content {
  padding: 20px 0;
}

.search-container {
  padding: 16px;
  margin-bottom: 20px;
  background-color: #f5f7fa;
  border-radius: 4px;
}

.menu-name {
  display: flex;
  align-items: center;
}

.icon-input-container {
  display: flex;
  gap: 8px;
  align-items: center;
}

.icon-actions {
  display: flex;
  flex-shrink: 0;
  gap: 6px;
  align-items: center;
}

.icon-picker {
  min-height: 320px;
}

.icon-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}

.icon-item {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 10px 12px;
  cursor: pointer;
  border: 1px solid #ebeef5;
  border-radius: 6px;
  transition: all 0.2s ease;
}

.icon-item:hover {
  border-color: #409eff;
  box-shadow: 0 2px 8px rgb(64 158 255 / 15%);
}

.icon-name {
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 12px;
  color: #666;
  white-space: nowrap;
}

:deep(.el-table) {
  .el-table__row {
    .el-table__cell {
      padding: 8px 0;
    }
  }
}

:deep(.el-tree-select) {
  .el-select__wrapper {
    width: 100%;
  }
}
</style>
